package com.damon.thread;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Socket;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Types;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.damon.entity.PrintDeviceEntity;
import com.damon.log.WcsLog;
import com.damon.utils.DbUtil;
import com.damon.utils.GlobalOjbectUtil;
import com.damon.utils.LogUtil;

public class PrintSocketThread extends Thread{
//	Logger logger = LoggerFactory.getLogger(PrintSocketThread.class);
	WcsLog logger;
	PrintDeviceEntity deviceInfo;
	
	public PrintSocketThread(PrintDeviceEntity printDeviceEntity) {
		this.deviceInfo = printDeviceEntity;
		this.logger = LogUtil.getLogger(PrintSocketThread.class, deviceInfo);
	}
	
	@Override
	public void run() {
		String devNum = deviceInfo.getDeviceNumber();
		String ip = deviceInfo.getIp();
		int port = deviceInfo.getPort();
		String devInfo = "["+devNum+"] ["+ip+":"+port+"]";
		Socket socket = null;
		OutputStream os = null;
		while(true) {
			try {
//				logger.info("开始为：["+ip+":"+port+"]建立连接！");
				socket = new Socket(ip,port);
				os = socket.getOutputStream();
				logger.info("设备地址：["+ip+":"+port+"]连接成功！");
				//用于打印已连接设备信息
				GlobalOjbectUtil.getConnecteDDeviceSet().add(devInfo);
				GlobalOjbectUtil.getWindow().getDeviceStatusLabel()
								//.setText("已连接设备："+GlobalOjbectUtil.getConnecteDDeviceSet());
								.setText("已连接设备数："+GlobalOjbectUtil.getConnecteDDeviceSet().size());
				try {
					//该嵌套循环用于执行业务：循环查找任务表，并发给打印机，最后更新打印状态
					while(true) {
						
						try {
							long start = System.currentTimeMillis();
							ArrayList<Object> list = getToPrinterMsg(ip, port);
							Integer id = (Integer) list.get(0);
							String msg = (String) list.get(1);
							String logMsg = (String) list.get(2);
							if("".equals(msg) == false) {
//								String zpl1 = "^XA^CI28^CW1,E:SIMSUN.FNT^MMT^PW440^LL0735^LS0^FT229,58^A1R,20,20^FD";
//								String zpl2 = "^FS^PQ1,0,1,Y^XZ";
								
								logger.info("打印信息[id: "+id+"] [msg: "+logMsg+"]");
//								msg = zpl1 + msg + zpl2;
								//如果网络断开或打印机突然关机，流断开，表中打印标志不会修改，连接后可以重打！
								os.write(msg.getBytes("utf-8"));
								updataPrintState(id);
								long end = System.currentTimeMillis();
								logger.info("打印完成，数据id："+id+",耗时："+(end -start)+"ms!\n");
							}
							else {
//								logger.info("空");
								//输出一个空格，为了在打印机关机时，触发输出流异常，即时发现关机情况
								os.write(" ".getBytes("utf-8"));
//								StringBuffer str = new StringBuffer();
//								for(int i=0;i<100;i++) {
//									str.append("输出一个空格，为了在打印机关机时，触发输出流异常，即时发现关机情况\r\n");
//								}
								
//								logger.info(str.toString());
//								Thread.sleep(50);
							}
							//业务阻塞，循环读取业务表的间隔
							Thread.sleep(1000);
						} catch (SQLException e) {
							logger.error("执行打印任务时，调用存储过程(sql)产生错误！",e);
							e.printStackTrace();
						} 
					}
				}catch (IOException e) {
					logger.error("执行打印任务时，输出流产生错误，打印机服务端已关闭！",e);
					e.printStackTrace();
				} 
//				catch (SQLException e) {
//					logger.error("执行打印任务时，调用存储过程(sql)产生错误！");
//					e.printStackTrace();
//				} 
				catch (InterruptedException e) {
					logger.error("执行打印任务时，线程阻塞sleep方法产生错误！",e);
					e.printStackTrace();
				}finally {
					//用于向状态栏更已连接设备信息
					GlobalOjbectUtil.getConnecteDDeviceSet().remove(devInfo);
					GlobalOjbectUtil.getWindow().getDeviceStatusLabel()
//									.setText("已连接设备："+GlobalOjbectUtil.getConnecteDDeviceSet());
					.setText("已连接设备数："+GlobalOjbectUtil.getConnecteDDeviceSet().size());
				}
			} catch (IOException e) {
//				logger.error("设备地址：["+ip+":"+port+"]，连接建立失败，请检测打印机是否正常开启！",e);
				e.printStackTrace();
			} finally {
				
				try {
					if(os != null) {
						os.close();
					}
					if (socket != null) {
						socket.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			//打印机重连时间：1s
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				logger.error("重连打印机时，线程阻塞sleep方法产生错误！",e);
				e.printStackTrace();
			}
		}

	}
	/**
	 * 调用存储过程，获取最近一条需要打印的数据、及该行数据id
	 * @param ip
	 * @param port
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Object> getToPrinterMsg(String ip,int port) throws SQLException {
		//参数：1、输入参数ip(varchar) 2、输入参数port(int) 3、@时间input_time varchar(50) 当前时间
		//      4、输出参数id(int)打印任务id 5、输出参数msg(varchar)发给你打印机的报文 6、@output_log_msg varchar(5000) output客户端的提示报文
		String sql = "{call sp_crerte_print_msg(?,?,?,?,?,?)}";
		Connection connection = null;
		CallableStatement call = null;
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
			String formateTime = sdf.format(new java.util.Date());
			connection = DbUtil.getConnection();
			call = connection.prepareCall(sql);
			call.setString(1, ip);
			call.setInt(2, port);
			call.setString(3, formateTime);
			call.registerOutParameter(4, Types.INTEGER);
			call.registerOutParameter(5, Types.VARCHAR);
			call.registerOutParameter(6, Types.VARCHAR);
			call.execute();
			ArrayList<Object> resultList = new ArrayList<>();
			//如果表里没有任务，数据库会把id返回空，结果集会取到0
			Integer id = call.getInt(4);
			resultList.add(id);
			//如果表里没有任务，数据库会把msg返回空，结果集会取到空字符串，不是null
			String msg = call.getString(5);
			resultList.add(msg);
			String logMsg = call.getString(6);
			resultList.add(logMsg);
			return resultList;
		} finally {
			if(call != null) {
				call.close();
			}
			if(connection != null) {
				connection.close();
			}
		}
	}
	/**
	 * 调用存储过程，将参数id下的数据，更新为已打印状态
	 * @param id
	 * @throws SQLException
	 */
	public void updataPrintState(int id) throws SQLException {
		//参数：1、输入参数id(int) 
		String sql = "{call sp_update_is_print_to_ok(?)}";
		Connection connection = null;
		CallableStatement call = null;
		try {
			connection = DbUtil.getConnection();
			call = connection.prepareCall(sql);
			call.setInt(1, id);
			call.execute();
//			logger.info("打印状态已更新，数据id："+id);
		} finally {
			if(call != null) {
				call.close();
			}
			if(connection != null) {
				connection.close();
			}
		}
	}
}
